package es.us.lsi.daw.controllers;

import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import es.us.lsi.daw.model.security.Group;
import es.us.lsi.daw.model.security.User;
import es.us.lsi.daw.model.security.WebUser;
import es.us.lsi.daw.model.security.enums.GroupEnum;
import es.us.lsi.daw.servicios.MessageService;
import es.us.lsi.daw.servicios.Validar;
import es.us.lsi.daw.soportePropiedades.GroupEnumEditor;
import es.us.lsi.daw.util.Util;
import es.us.lsi.daw.util.Vista;


@Controller
@SessionAttributes({"usuario", "dtoWebUserConfiguration"})
public class ControllerUser extends ControllerGenerico {

	@Autowired
	Validar validacion;
	
	//TODO(mamuso) This can be erased, can't it?
	@InitBinder
	public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(GroupEnum.class, new GroupEnumEditor());
    }

	
	@ModelAttribute("groups")
	public Group[] groups() {
		return daoAuthorization.getAllGroups();
	}

	@RequestMapping(value = PRIVADO + "listUser.do")
	public <T> ModelAndView listUserGET(ModelMap modelo, @RequestParam(value = "pagina", required = false) String pagina,
			@RequestParam(value = "numMaxRegistros", required = false) Integer numMaxRegistros, @RequestParam(value = "name", required = false) String nombre, @RequestParam(value = "surname",
					required = false) String apellidos, @RequestParam(value = "paginado", required = false) String paginado) {
		if ((nombre != null && !nombre.isEmpty()) || (apellidos != null && !apellidos.isEmpty())) {
			modelo.addAllAttributes(paginacion.paginacionUsuariosFiltro(pagina, numMaxRegistros, nombre, apellidos));
		} else {
			modelo.addAllAttributes(paginacion.paginacionUsuarios(pagina, User.class, User.A_GROUPS, numMaxRegistros));
			nombre = "";
			apellidos = "";
		}

		modelo.addAttribute("name", nombre);
		modelo.addAttribute("surname", apellidos);

		return new ModelAndView(Vista.LIST_USER, modelo);
	}

	@RequestMapping(value = PRIVADO + "deleteUser.do", method = RequestMethod.GET)
	public ModelAndView borrarUsuarioGET(ModelMap modelo, @RequestParam(value = "idUsuario") Long idUsuario) {
		//TODO(mamuso) New Authorization
		if (idUsuario != null) {
			this.daoUsuario.eliminarUsuario(idUsuario);
		}
		modelo.addAttribute("mensaje_ok","Usuario eliminado correctamente.");
		return new ModelAndView("redirect:listadoUsuario.do",modelo);
	}

	@RequestMapping(value = PRIVADO + "formUser.do", method = RequestMethod.GET)
	public ModelAndView formUsuarioGET(ModelMap modelo, @RequestParam(value = "idUsuario", required = false) Long idUsuario) {

		//TODO(mamuso)add authorization
//		WebUser webUser = (WebUser)daoAuthentication.getCurrentUser();
		
		WebUser usuario;
		if (idUsuario != null) {
			usuario = this.daoComun.obtenerObjetoId(WebUser.class, idUsuario);
		} else { //NOTE(mamuso): I don't know when this is used
			usuario = new WebUser();
			usuario.setEnabled(true);
		}
		modelo.addAttribute("usuario", usuario);

		return new ModelAndView(Vista.FORM_USER, "modelo", modelo);
	}

	//TODO: modificar comportamiento.
	@RequestMapping(value = PRIVADO + "formUser.do", method = RequestMethod.POST)
	public ModelAndView formUsuarioPOST(@ModelAttribute("usuario") WebUser webUser, BindingResult result, ModelMap modelo, @RequestParam(value = "pagina", required = false) Integer pagina) {

		//TODO(mamuso) Add authorization
		validar.validate(webUser, result);
		
		Collection<? extends GrantedAuthority> authorities =  webUser.getAuthorities();
		if (authorities == null || authorities.isEmpty()) {
			result.rejectValue("listaRoles", "requerido.rol");
		}
		if (!result.hasFieldErrors(User.A_PASSWORD) && webUser.isPasswordChange()) {
			if (webUser.getRepeatPassword() != null && !webUser.getRepeatPassword().isEmpty()) {
				if (!webUser.getPassword().equals(webUser.getRepeatPassword())) {
					result.rejectValue("repeatPassword", "message.error.incorrect.repetirclave");
//[sic]//					user.resetPassword(); 
				}
			} else {
				result.rejectValue("repeatPassword", "message.error.required.repetirclave");
//[sic]//				user.resetPassword();
			}
		}
		if (result.hasErrors()) {
//[sic]//			user.resetPassword();
			return new ModelAndView(Vista.FORM_USER, modelo);
		}

		Set<Group> groups = webUser.getGroups();
		if (groups != null && groups.size() > 0) {
			webUser.setGroups(groups);
		}
		this.daoComun.guardarObjeto(webUser);
		return new ModelAndView("redirect:listUser.do?pagina=" + pagina, modelo);

	}

	@RequestMapping(value = PRIVADO + "eliminarUsuarios.do", method = RequestMethod.POST)
	public String eliminarUsuariosPOST(ModelMap modelo, @RequestParam(value = "pagina", required = false) String pagina, @RequestParam(value = "usuariosSel", required = false) List<Long> usuariosSel) {
		if (pagina == null) {
			pagina = "1";
		}
		if (usuariosSel != null && !usuariosSel.isEmpty()) {
			User userToDelete = null;
			for (Long idUser : usuariosSel) {
				userToDelete = new User();
				userToDelete = daoComun.obtenerObjetoId(User.class, idUser, User.A_GROUPS);
				daoUsuario.eliminarUsuario(userToDelete.getId());
			}
		}
		modelo.clear();
		return "redirect:listUser.do?pagina=" + pagina;
	}

	@RequestMapping(value = PRIVADO + "cambiarClaveUsuarios.do", method = RequestMethod.POST)
	public String cambiarClaveUsuariosPOST(ModelMap modelo, @RequestParam(value = "pagina", required = false) Long pagina, @RequestParam(value = "usuariosSel", required = false) List<Long> usuariosSel) {
		//TODO(mamuso) check that usuariosSel gets the WebUser id and not the User id!
		if (usuariosSel != null && !usuariosSel.isEmpty()) {

			WebUser userToEdit = null;
			String newPass = null;
			MessageService message = null;
			String messageContent = "";

			message = new MessageService();
			messageContent += message.obtenerMensaje("label.text.content.newpass");
			for (Long idUser : usuariosSel) {
				userToEdit = daoComun.obtenerObjetoId(WebUser.class, idUser);
				if (userToEdit != null) {
					// Obtener la clave aleatoria y asociarla al usuario
					newPass = Util.getPassword();
					userToEdit.setPassword(Util.encriptarPassword(newPass));
					daoComun.guardarObjeto(userToEdit);
				}
			}
		}
		return "redirect:listUser.do?pagina=" + pagina;
	}

}
